<template>
  <div ref="keyboard" class="numberKeyboard_wrapper">
    <transition name="keyboard">
      <div v-if="show" class="numberKeyboard_body">
        <div v-for="item in keyboardList" :key="item.value" class="numberKeyboard_body_item" @click="clickKeyboard(item)">
          {{ item.label }}
        </div>
      </div>
    </transition>
  </div>
</template>
<script>
export default {
  props: {
    visible: { // 显示控制
      type: Boolean,
      required: true
    },
    value: { // v-model传入的值
      type: String,
      default: ''
    },
    inputElement: { // 传入整页dom节点 || 输入框dom节点（根据需求选择测试）
      type: [Object, HTMLElement],
      default: () => ({})
    }
  },
  data() {
    return {
      keyboardList: [
        { label: '1', value: '1' },
        { label: '2', value: '2' },
        { label: '3', value: '3' },
        { label: '4', value: '4' },
        { label: '5', value: '5' },
        { label: '6', value: '6' },
        { label: '7', value: '7' },
        { label: '8', value: '8' },
        { label: '9', value: '9' },
        { label: '0', value: '0' },
        { label: 'A', value: 'A' },
        { label: 'B', value: 'B' },
        { label: 'C', value: 'C' },
        { label: 'D', value: 'D' },
        { label: 'E', value: 'E' },
        { label: 'F', value: 'F' },
        { label: 'G', value: 'G' },
        { label: 'H', value: 'H' },
        { label: 'I', value: 'I' },
        { label: 'J', value: 'J' },
        { label: 'K', value: 'K' },
        { label: 'L', value: 'L' },
        { label: 'M', value: 'M' },
        { label: 'N', value: 'N' },
        { label: 'O', value: 'O' },
        { label: 'P', value: 'P' },
        { label: 'Q', value: 'Q' },
        { label: 'R', value: 'R' },
        { label: 'S', value: 'S' },
        { label: 'T', value: 'T' },
        { label: 'U', value: 'U' },
        { label: 'V', value: 'V' },
        { label: 'W', value: 'W' },
        { label: 'X', value: 'X' },
        { label: 'Y', value: 'Y' },
        { label: 'Z', value: 'Z' },
        { label: '后退', value: '-1' },
        { label: '清除', value: '-2' }
      ]
    }
  },
  computed: {
    show: {
      get() {
        return this.visible
      },
      set(newVal) {
        this.$emit('update:visible', newVal)
      }
    },
    keyboardValue: { // 利用计算属性更新
      get() {
        return this.value
      },
      set(newVal) {
        this.$emit('input', newVal)
      }
    }
  },
  watch: {
    // 禁止背景滚动 && 键盘显示时，判断距离会遮住输入框dom时，把输入框dom往上推
    show(newVal) {
      if (newVal) {
        document.body.style.overflow = 'hidden';
      } else {
        document.body.style.overflow = '';
      }
      Object.keys(this.inputElement).length > 0 && this.keyboardHandle(newVal) // 有传入dom时执行
    }
  },
  mounted() {
    // 插入body
    document.body.appendChild(this.$el);
    // 添加全局关闭事件侦听器
    document.addEventListener('click', this.handleOutsideClick, true);
  },
  destroyed() {
    // 组件销毁后同步清除元素
    this.$el.parentNode.removeChild(this.$el);
    // 移除全局关闭事件侦听器
    document.removeEventListener('click', this.handleOutsideClick, true);
  },
  methods: {
    // 键盘显示时，判断距离会遮住输入框dom时，把输入框dom往上推
    async keyboardHandle(visible) {
      await this.$nextTick()
      if (visible) { // 键盘打开
        const inputElement = this.inputElement // 输入框dom
        const keyboardElement = this.$refs.keyboard // 键盘组件dom
        const windowHeight = window.innerHeight; // 游览器视口高度
        const inputElementTop = inputElement.getBoundingClientRect().bottom; // 输入框dom元素底部 距离当前视口顶部距离
        const keyboardTop = windowHeight - keyboardElement.offsetHeight // 可视高度 - 键盘高度 = 键盘距离可视区域顶部距离
        if (inputElementTop > keyboardTop) { // 输入框被键盘遮挡情况
          console.log('输入框被键盘遮挡了')
          inputElement.style.transition = 'transform 0.3s' // 加上过渡效果
          inputElement.style.transform = `translateY(-${
            inputElementTop - (windowHeight - keyboardElement.offsetHeight)
          }px)`;
        } else {
          console.log('输入框没有被键盘遮挡情况')
        }
      } else { // 键盘关闭，恢复输入框的位置
        this.inputElement.style.transform = 'translateY(0)';
      }
    },
    // 点击键盘按钮回调
    // 更新计算属性值 会自动触发更新 value值
    clickKeyboard({ value, label }) {
      const decimalPoint = /\./g // 小数点正则
      switch (value) {
        case '-1':
          this.keyboardValue = this.keyboardValue.slice(0, -1)
          break;
        case '.': // 只允许输入一个小数点
          if (!decimalPoint.test(this.keyboardValue)) {
            this.keyboardValue += label
          }
          break;
        case '-2':
          this.keyboardValue = ''
          break
        default:
          this.keyboardValue += label
          break;
      }
      this.$emit('change', this.keyboardValue)
    },
    // 点击键盘外部区域关闭键盘
    handleOutsideClick(event) {
      if (this.$refs.keyboard && !this.$refs.keyboard.contains(event.target)) {
        this.show = false
      }
    }
  }
}
</script>
<style lang="less" scoped>
.numberKeyboard{
  &_wrapper{
    width: 100%;
    position: fixed;
    bottom: 0;
    left: 0;
    display: flex;
    justify-content: center;
  }
  &_body{
    width: 100%;
    max-width: 800px;
    height: 60vh;
    background-color:#f2f3f5;
    display: flex;
    flex-wrap: wrap;
    padding: 10px;
    border-radius: 10px 10px 0 0;
    border: 1px solid #EBEEF5;
    &_item{
      flex:0 0 11.11%;
      margin: 10px 10px 10px 10px;
      height: 50px;
      background-color: #fff;
      border-radius: 10px;
      font-size: 22px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: bold;
      cursor: pointer;
    }
    &_item:active{
      background-color: #dcdee0;
    }
    &_item:nth-child(3n) {
      margin-right: 0;
    }
    &_item:nth-child(n+10):nth-child(-n+12){
      margin-bottom: 0;
    }
  }
}

.keyboard-enter-active,.keyboard-leave-active { // 元素进入和离开时的过渡动画定义
  transition: transform 0.3s;
}
.keyboard-enter,.keyboard-leave-to { // 元素进入和离开时的动作
  transform: translateY(100%);
}
</style>
